在上一篇文章當中,我們提到可以使用物件來模擬真實世界的事物,那麼我們就來嘗試建立幾個棒球選手的物件吧!
首先,我們建立一個叫做 shohei
的物件,當中有一個屬性 name
,以及一個方法 hit
const shohei = {
name: 'shohei',
hit: function () {
console.log(`${this.name} can hit!`)
}
}
接下來,讓我們同樣建立另外一個棒球選手物件 ohtani
,擁有相同的屬性與方法,只是名字不太一樣
const ohtani = {
name: 'ohtani',
hit: function () {
console.log(`${this.name} can hit!`)
}
}
完成之後,我們就可以操作這些物件,譬如取得屬性的值,或是呼叫方法:
shohei.name // shohei
ohtani.name // ohtani
shohei.hit() // shohei can hit!
ohtani.hit() // ohtani can hit!
現在我們已經有兩位棒球選手了,不過如果要打比賽的話,至少還要另外建立七位選手,也就是要重複這段程式碼七次:
const xxx = {
name: 'xxx',
hit: function () {
console.log(`${this.name} can hit!`)
}
}
同時會發現,這些物件的屬性、方法都一模一樣,只差在屬性 name
的值不一樣。那麼我們可以建立一個像是蛋糕模的東西,幫我們快速產生許多一模一樣的蛋糕(結果)嗎?
在物件導向程式設計當中的確有這種東西,它就叫「類別」(class)。這裡我們先跳過定義,先快速來實作一下。
首先,先建立一個叫做 BaseballPlayer
的類別,當中包含了 name
屬性和 hit
方法。另外透過 constructor 來接收並指派創建物件時所輸入的資訊。
class BaseballPlayer {
name: string
constructor(name: string) {
this.name = name
}
hit() {
console.log(`${this.name} can hit`)
}
}
接下來,我們就可以使用 BaseballPlayer
類別來快速產生另外兩個物件:
const ichiro = new BaseballPlayer('ichiro')
const shuzuki = new BaseballPlayer('shuzuki')
最後,就可以得到我們當初所期待的物件們
ichiro.hit() // ichiro can hit!
suzuki.hit() // huzuki can hit!
在程式設計當中,類別是一種程式碼的範本,可以用來建立物件、描述當中的屬性與方法,以及提供初始狀態。
In object-oriented programming, a class is an extensible program-code-template for creating objects, providing initial values for state (member variables) and implementations of behavior (member functions or methods).
在剛剛 BaseballPlayer
這個類別的例子當中
class BaseballPlayer {
name: string
constructor(name: string) {
this.name = name
}
hit() {
console.log(`${this.name} can hit`)
}
}
我們描述了一個屬性 name
、一個方法 hit
,以及透過 constructor 提供初始狀態。而透過類別所建立的物件,通常稱作實例 (instance)。在剛剛的例子當中,ichiro
和 suzuki
都是 BaseballPlayer
這個類別的實例。
反過來看,一個類別其實也提供了「規範」。以 BaseballPlayer
這個例子來說,它規範了 baseball players 所應該具備的屬性和方法。
除了自己親手建立一個新的類別之外,我們也可以透過「繼承」的方式,讓新的類別承接原有類別的屬性或方法。
舉例來說,我們希望建立一個游擊手 (short stop) 的類別,他除了要有基本 baseball player 的屬性和方法之外,還要新增一個 run 方法。所以這裡我們建立 Shortstop
類別,然後透過 extends 語法來繼承 BaseballPlayer
class Shortstop extends BaseballPlayer {
run() {
console.log(`${this.name} can run`)
}
}
之後,我們就可以用這個新的類別,來建立一位游擊手,一位又能打又能跑的棒球選手!
const jeter = new Shortstop('jeter')
jeter.hit() // jeter can hit
jeter.run() // jeter can run
類別除了能夠幫助我們快速建立相同類型的物件(實例)之外,還帶來了其他好處,像是
而因為有了「繼承」這個特性,我們甚至可以將不同類別當中的相同屬性或方法,抽取出來,建立一個 parent 類別,然後讓其他 child 類別繼承他的屬性或方法。同樣的方法,我們可以繼續做下去,產生 parent's parent、parent's parent’s parent 類別等等。
這就很像生物學當中的「界門綱目科屬種」的層層分類方式,以人來說,就被歸類於下面這樣的分類當中:
而你、我都是「智人」這個類別的實例,繼承了(包含了)人屬當中所描述的特徵,也包含了更上層類別的特徵。
在生物學當中,我們透過這樣分類法(林奈氏分類法)來整理世界上所有的生物,同樣的我們也可以透過這種方式,來建立各種、層層的類別,來模擬世界上的事物。
但是,如果今天我們只是想要用程式打造一個待辦清單的應用程式,其實不需要花這麼大的功夫去把所有世界上所有事物整理成各種類別,我們只要把跟待辦清單應用程式相關的事物整理起來就行。
不過這時候就會有另外一個問題,那就是在面對一個新的問題或情境時,我們該如何分類?我們該建立哪些的類別呢?這個就留待我們後續討論吧!
最後,分享一下一個有趣的影片